﻿using System;
using System.Collections.Generic;
using System.Reflection;
using NPOI.SS.UserModel;
using NetMicro.ExcelMapper.Attributes;

namespace NetMicro.ExcelMapper
{
    /// <summary>
    /// 列映射
    /// </summary>
    public class ColumnInfo : IColumnInfo
    {
        #region Fields

        //出于缓存目的，避免为每个单元格使用查找样式字典
        private ICellStyle _headerStyle;
        private ICellStyle _dataStyle;
        private bool _headerStyleCached;
        private bool _dataStyleCached;

        #endregion

        #region Properties

        /// <summary>
        /// 列标题的值
        /// </summary>
        public object HeaderValue { get; set; }

        /// <summary>
        /// 列属性相关
        /// </summary>
        public ColumnAttribute Attribute { get; set; }

        /// <summary>
        /// 最后一个非空白单元格值
        /// </summary>
        public object LastNonBlankValue { get; set; }

        /// <summary>
        /// 当前单元格值可能用于自定义解析
        /// </summary>
        public object CurrentValue { get; set; }

        /// <summary>
        /// 获取标题单元格格式
        /// </summary>
        public short? HeaderFormat { get; set; }

        /// <summary>
        /// 获取数据单元格格式
        /// </summary>
        public short? DataFormat { get; set; }

        #endregion

        #region 初始化

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="headerValue">列标题的值</param>
        /// <param name="columnName">列名</param>
        /// <param name="pi">映射属性类型信息.</param>
        public ColumnInfo(object headerValue, string columnName, PropertyInfo pi)
        {
            HeaderValue = headerValue;
            Attribute = new ColumnAttribute()
            {
                Name = columnName,
                Property = pi
            };
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="headerValue">列标题的值</param>
        /// <param name="columnIndex">列索引</param>
        /// <param name="pi">映射属性类型信息</param>
        public ColumnInfo(object headerValue, int columnIndex, PropertyInfo pi)
        {
            HeaderValue = headerValue;
            Attribute = new ColumnAttribute()
            {
                Index = columnIndex,
                Property = pi
            };
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="headerValue">列标题的值</param>
        /// <param name="attribute">列属性相关</param>
        public ColumnInfo(object headerValue, ColumnAttribute attribute)
        {
            if (attribute == null)
                throw new ArgumentNullException(nameof(attribute));

            Attribute = attribute;
            HeaderValue = headerValue;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// 刷新LastNonBlankValue和CurrentValue属性，然后根据UseLastNonBlankValue属性返回值。
        /// </summary>
        /// <param name="value">当前单元格的值</param>
        /// <returns>
        public object RefreshAndGetValue(object value)
        {
            CurrentValue = value;

            if (string.IsNullOrWhiteSpace(value as string))
            {
                return Attribute.UseLastNonBlankValue == true ? LastNonBlankValue : value;
            }

            LastNonBlankValue = value;

            return value;
        }

        /// <summary>
        /// 设置要导出的单元格的样式。
        /// 假设单元格属于当前列。
        /// </summary>
        /// <param name="cell">单元格设置</param>
        /// <param name="value">单元格值对象</param>
        /// <param name="isHeader">true则使用HeaderFormat；否则使用DataFormat</param>
        /// <param name="defaultFormats">默认格式.</param>
        /// <param name="helper"></param>
        public void SetCellStyle(ICell cell, Dictionary<short, ICellStyle> builtinStyles, Dictionary<string, ICellStyle> customStyles, object value, bool isHeader, Dictionary<Type, string> defaultFormats)
        {
            if (cell == null) throw new ArgumentNullException(nameof(cell));

            if (isHeader && !_headerStyleCached)
            {
                _headerStyle = MapperHelper.GetCellStyle(cell, builtinStyles, customStyles, null, HeaderFormat);

                if (_headerStyle == null && HeaderValue != null)
                {
                    _headerStyle = MapperHelper.GetDefaultStyle(cell.Sheet.Workbook, customStyles, HeaderValue, defaultFormats);
                }

                _headerStyleCached = true;
            }
            else if (!isHeader && !_dataStyleCached)
            {
                _dataStyle = MapperHelper.GetCellStyle(cell, builtinStyles, customStyles, Attribute.CustomFormat, DataFormat);

                if (_dataStyle == null && value != null)
                {
                    _dataStyle = MapperHelper.GetDefaultStyle(cell.Sheet.Workbook, customStyles, value, defaultFormats);
                }

                _dataStyleCached = true;
            }

            cell.CellStyle = isHeader ? _headerStyle : _dataStyle;
        }

        #endregion
    }
}
